package aa;

import java.util.ArrayList;
import java.util.*;
import java.util.UUID;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.MessageDigest;

public class helpFunc {
	static short bs = 30000;
	static int g_packId=0;
//	static String serviceKey = "bigSalt";
//	public static short pushAhead=2000;
	//public static int packLimit=1400;
	public static int con_close=66;
	//public static int con_localPort = 9997;
	//public static int con_portDecreaseDose=1;
	//public static String con_serverIp = "154.221.19.38";//"192.168.43.173";
	//public static int con_serverPort = 19022;
	//public static String con_serverIp = "192.168.43.173";
//	public static int speedLimit = 250;
//	public static int perSecondPortsLimit=50;
	public static int minPackGot=100;
	public static double con_maxRate = 0.5;
	public static double con_minRate = 0.08;
	public static double timeoutTime = 1;
	public static int speedLimit_portNum = 10;
	//public static int	con_portIncreaseDose=3;
	public static byte[] uuid,con;
	public static int recLen = 10240;
	public static int regulateTimeSpan=1;
	public static int con_streamBufferSize = 200 * 1024;
	//public static int maxPortNum = 100;
	public static int 	minPortNum = 10;
	private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
	public static String bytesToHex(byte[] bytes) {
	    char[] hexChars = new char[bytes.length * 2];
	    for (int j = 0; j < bytes.length; j++) {
	        int v = bytes[j] & 0xFF;
	        hexChars[j * 2] = HEX_ARRAY[v >>> 4];
	        hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
	    }
	    return new String(hexChars);
	}
	
	public static short circleBig(short a, short b) {
		if (a == b)
			return a;
		if ((a > b) && ((a - b) < (bs / 2)))
			return a;
		if ((a < b) && ((b - a) > (bs / 2)))
			return a;
		return b;
	}

	public static short circleAddOne(short a) {
		if (a == bs - 1)
			return 0;
		return (short) (a + 1);
	}

	public static short circleAdd(short a, short b) {
		short ret = a;
		for (short i = 0; i < b; i++) {
			ret = circleAddOne(ret);
		}

		return ret;
	}

	public static ArrayList<Short> circleRange(short a, short b) {
		short temp = a;
		ArrayList<Short> ret = new ArrayList<Short>();
		while (true) {
			if (temp == circleBig(b, temp))
				break;
			ret.add(temp);
			temp = circleAdd(temp, (short) 1);
		}
		return ret;

	}

	public static double getTime() {
		return System.currentTimeMillis() / (double) 1000;
	}

	public static void addPackSta(Map<String, packStaData> m, short v, double ti) {
		if (ti == 0 || ti == -Double.MAX_VALUE) {
			ti = getTime();
		}
		String u = UUID.randomUUID().toString();
		m.put(u, new packStaData(ti, v));
	}

	public static String getMulString(String a, int n) {
		String	ret =new String();
		for (int i = 0; i < n; i++) {
			ret+=  a;
		}
		return ret;
	}

	public static short getPackStaBigV(Map<String, packStaData> m) {
		short mv = 0;
		for (String k : m.keySet()) {
			packStaData v = m.get(k);
			if (getTime() - v.time < 1 && v.v > mv)
				mv = v.v;
		}
		return mv;
	}
	public static void  clearPackSta(Map<String, packStaData> m)
	{
		ArrayList<String> k = new ArrayList<String>(m.keySet());
		for(String i:k)
		{
			if(m.get(i).time<getTime()-1)
				m.remove(i);
		}
	}
	 public static void print(String a) {
		System.out.println(a);
	}
	
	 public static void  makePack  (byte[] s,byte[] salt) throws Exception
	 {
		 g_packId+=1;
		 if (g_packId>30000)g_packId=0;
		 structWrapper w= new structWrapper(s.length+6);
		 w.writeWord((short)g_packId);
		 w.writeArr(s);
		 MessageDigest md=	 MessageDigest.getInstance("MD5");
		 md.update(w.data,0,s.length+2);
		md.update(salt);		
		 byte[] aa=md.digest();
		 System.arraycopy(aa, 0, w.data, s.length+2, 4);
		 uuid = new byte[2];
		
		 System.arraycopy(w.data,0,uuid,0,2);
		 con = w.data;
	 }
	 public static byte[]  getuuid_byte() throws Exception
	 {
		return MessageDigest.getInstance("MD5").digest( UUID.randomUUID().toString().getBytes());
	 }
	 public static byte[] bufAdd( byte[] a, byte[] b)
	 {
		 byte[] newMd5 = new byte[a.length+b.length];
		 System.arraycopy(a, 0, newMd5, 0, a.length);
		 System.arraycopy(b, 0, newMd5, a.length, b.length);
		 return newMd5;
	 }

	 public static void checkPackValid2(byte[] s,byte[] salt)
	 throws Exception
	 {
		 if(s.length<4)
		 {
			 uuid = new byte[0];
			 con = new byte[0];
			 return;
		 }
		 
		 MessageDigest md=	 MessageDigest.getInstance("MD5");
		 md.update(s,0,s.length-4);
		md.update(salt);
		
		 byte[] aa=md.digest();
		 byte[] newMd5 = new byte[4];
		 System.arraycopy(aa, 0, newMd5, 0, 4);
		 byte[] oriMd5 = new byte[4];
		 System.arraycopy(s,s.length-4,oriMd5,0,4);
		 
		 if(!Arrays.equals(newMd5,oriMd5))
		 {
			 uuid = new byte[0];
			 con = new byte[0];
			 return;
		 }
		 uuid = new byte[2];
		 con = new byte[s.length-6];
		 System.arraycopy(s,0,uuid,0,2);
		 System.arraycopy(s,2,con,0,s.length-6);		 
	}
}

class structWrapper {
	byte[] data;
	int pos;
int leftLen()
{
	return data.length-pos;}
	structWrapper(int l) {
		data = new byte[l];
		pos = 0;
	}

	structWrapper(byte[] data2) {
		data = data2;
		pos = 0;
	}

	public void writeByte(byte b) {
		data[pos] = b;
		pos += 1;
	}

	public void writeWord(short s) {
		byte[] t = ByteBuffer.allocate(2).order(ByteOrder.nativeOrder()).putShort(s).array();
		System.arraycopy(t, 0, data, pos, 2);
		pos += 2;
	}
	
	public void writeDWord(int s) {
		byte[] t = ByteBuffer.allocate(4).order(ByteOrder.nativeOrder()).putInt(s).array();
		System.arraycopy(t, 0, data, pos, 4);
		pos += 4;
	}
	
	public void writeArr(byte[] s)
	{
		System.arraycopy(s, 0, data, pos, s.length);
		pos +=  s.length;
	}
	public byte[] readArr(int n)
	{
		 byte[] re=	new byte[n];
		 
		System.arraycopy(data, pos, re, 0,n);
		pos +=  n;
		return re;
	}

	public void writeDouble(double d) {
		byte[] t = ByteBuffer.allocate(8).order(ByteOrder.nativeOrder()).putDouble(d).array();
		System.arraycopy(t, 0, data, pos, 8);
		pos += 8;
	}

	public byte[] getWriteData() {
		byte[] d = new byte[pos];
		System.arraycopy(data, 0, d, 0, pos);
		return d;
	}

	public byte readByte() {
		pos += 1;
		return data[pos - 1];

	}

	public short readWord() {
		pos += 2;
		return ByteBuffer.wrap(data, pos - 2, 2).order(ByteOrder.nativeOrder()).getShort();
	}
	public int readDWord() {
		pos += 4;
		return ByteBuffer.wrap(data, pos - 4, 4).order(ByteOrder.nativeOrder()).getInt();
	}
	public double readDouble() {
		pos += 8;
		return ByteBuffer.wrap(data, pos - 8, 8).order(ByteOrder.nativeOrder()).getDouble();
	}

	public byte[] getLeftData() {
		byte[] d = new byte[data.length - pos];
		System.arraycopy(data, pos, d, 0, data.length - pos);
		return d;
	}
}
